/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.service.impl;

import com.xy.biz.base.domain.bo.EquipmentBO;
import com.xy.biz.base.domain.converter.EquipmentConverter;
import com.xy.biz.base.domain.query.EquipmentQuery;
import com.xy.biz.base.domain.req.SaveEquipmentRequest;
import com.xy.biz.base.manager.EquipmentManager;
import com.xy.biz.base.service.EquipmentService;
import com.xy.lang.domain.Result;
import com.xy.lang.enums.ApplyStatusEnum;
import com.xy.lang.enums.OccupyStatusEnum;
import com.xy.tool.context.UserContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 *
 *
 * @author yzh
 * @date 2021-4-13
 */
@Slf4j
@Service
public class EquipmentServiceImpl implements EquipmentService, InitializingBean {

    @Autowired
    private EquipmentManager equipmentManager;
    @Autowired
    private EquipmentEventBus equipmentEventBus;

    @Override
    public Result<?> saveEquipment(SaveEquipmentRequest request) {
        //判断编号是否重复
        int count = equipmentManager.countEquipment(EquipmentQuery.builder().equipmentCode(request.getEquipmentCode()).build());
        if (count > 0) {
            return Result.ofErrorData(Result.CONFLICT, "已存在的仪器编码");
        }
        EquipmentBO equipmentBO = EquipmentConverter.toBO(request);
        //数据完善
        buildEquipment(equipmentBO);
        int affectedRows = equipmentManager.saveEquipment(equipmentBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    private void buildEquipment(EquipmentBO equipmentBO) {
        LocalDateTime now = LocalDateTime.now();
        equipmentBO.setCreateTime(now);
        equipmentBO.setUpdateTime(now);
        equipmentBO.setTenantId(UserContextHolder.getTenantId());
        equipmentBO.setStatus(ApplyStatusEnum.START.getCode());
        equipmentBO.setCreateUserId(UserContextHolder.getUserId());
        equipmentBO.setCreateUserName(UserContextHolder.getUserName());
        equipmentBO.setUpdateUserId(UserContextHolder.getUserId());
        equipmentBO.setUpdateUserName(UserContextHolder.getUserName());
        equipmentBO.setUserGroupId(UserContextHolder.getUserGroupId());
    }

    @Override
    public Result<?> saveAllEquipment(Collection<EquipmentBO> collection) {
        int affectedRows = equipmentManager.saveAllEquipment(collection);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> updateEquipment(SaveEquipmentRequest request) {
        EquipmentBO equipmentBO = EquipmentConverter.toBO(request);
        equipmentBO.setUpdateTime(LocalDateTime.now());
        int affectedRows = equipmentManager.updateEquipment(equipmentBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> updateEquipmentStatus(SaveEquipmentRequest request) {
        EquipmentBO equipmentBO = EquipmentConverter.toBO(request);
        LocalDateTime now = LocalDateTime.now();
        equipmentBO.setUpdateUserName(UserContextHolder.getUserName());
        equipmentBO.setUpdateUserId(UserContextHolder.getUserId());
        equipmentBO.setUpdateTime(now);
        int affectedRows = equipmentManager.updateEquipment(equipmentBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> deleteEquipment(Long equipmentId) {
        int affectedRows = equipmentManager.deleteEquipment(equipmentId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public EquipmentBO getEquipment(Long equipmentId) {
        return equipmentManager.getEquipment(equipmentId);
    }

    @Override
    public List<EquipmentBO> listEquipmentById(Collection<Long> collection) {
        return equipmentManager.listEquipmentById(collection);
    }

    @Override
    public List<EquipmentBO> listEquipment(EquipmentQuery query) {
        return equipmentManager.listEquipment(query);
    }

    @Override
    public int countEquipment(EquipmentQuery query) {
        return equipmentManager.countEquipment(query);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        equipmentEventBus.addOccupyEquipmentHandler((equipmentIdList) -> {
            if (CollectionUtils.isEmpty(equipmentIdList)) {
                return;
            }
            List<EquipmentBO> equipmentBOList =
                    equipmentManager.listEquipment(EquipmentQuery.max()
                            .equipmentIdList(equipmentIdList)
                            .occupyStatus(OccupyStatusEnum.FREE.getCode())
                            .build());
            if (CollectionUtils.isEmpty(equipmentBOList)) {
                log.error("设备锁定失败，设备不存在！");
            }
            if (equipmentIdList.size() != equipmentBOList.size()) {
                log.error("设备锁定部分失败，设备不存在或存在已占用设备：" + equipmentIdList
                        .removeAll(equipmentBOList.stream().map(EquipmentBO::getEquipmentId).collect(Collectors.toList())));
            }
            equipmentManager.lockup(equipmentIdList);
        });
        equipmentEventBus.addReleaseEquipmentHandler((equipmentIdList) -> {
            if (CollectionUtils.isEmpty(equipmentIdList)) {
                return;
            }
            List<EquipmentBO> equipmentBOList =
                    equipmentManager.listEquipment(EquipmentQuery.max()
                            .equipmentIdList(equipmentIdList)
                            .occupyStatus(OccupyStatusEnum.USING.getCode())
                            .build());
            if (CollectionUtils.isEmpty(equipmentBOList)) {
                log.error("设备解锁失败，设备不存在！");
            }
            if (equipmentIdList.size() != equipmentBOList.size()) {
                log.error("设备解锁部分失败，设备不存在或存在已空闲设备：" + equipmentIdList
                        .removeAll(equipmentBOList.stream().map(EquipmentBO::getEquipmentId).collect(Collectors.toList())));
            }
            equipmentManager.unlock(equipmentIdList);
        });
    }
}
